import { ref } from 'vue';

/**
 * 一个可组合函数，封装了拖拽、缩放、吸附和碰撞处理的核心逻辑。
 * @param {import('vue').Ref<Array<object>>} components - 组件列表的 ref。
 * @param {import('vue').Ref<HTMLElement>} gridContainer - 栅格容器的 DOM 引用 ref。
 * @param {object} gridConfig - 包含栅格几何信息的响应式对象。
 * @param {import('vue').Ref<number>} gridConfig.gridCellWidth
 * @param {import('vue').Ref<number>} gridConfig.gridCellHeight
 * @param {number} gridConfig.gridGap
 */
export function useDraggableGrid(components, gridContainer, gridConfig) {
    const { gridCellWidth, gridCellHeight, gridGap } = gridConfig;

    // --- 内部状态 ---
    const selectedId = ref(null);
    const snapGuide = ref({
        x: { show: false, pos: 0 },
        y: { show: false, pos: 0 }
    });

    // --- 辅助函数：碰撞检测 ---
    const checkCollision = (a, b) => {
        const tolerance = 1; // 1px 容差避免浮点数精度问题
        return !(
            a.x + a.width <= b.x + tolerance ||
            a.x >= b.x + b.width - tolerance ||
            a.y + a.height <= b.y + tolerance ||
            a.y >= b.y + b.height - tolerance
        );
    };

    // --- 事件处理器 ---

    const selectComponent = (id, e) => {
        if (e && e.target.classList.contains('delete-btn')) return;
        selectedId.value = id;
    };

    const onDragStart = (id, index) => {
        selectedId.value = id;
        const item = components.value[index];
        item.startX = item.x;
        item.startY = item.y;
    };

    const onDraging = (index) => {
        const item = components.value[index];
        const container = gridContainer.value;
        if (!container) return;

        const { clientWidth: containerWidth, clientHeight: containerHeight } = container;
        const colOffset = gridGap.value;

        // --- X 轴吸附 (不变) ---
        const gridStepX = Math.round(gridCellWidth.value) + gridGap.value;
        const nearestColIndex = Math.round((item.x - colOffset) / gridStepX);
        let snapX = colOffset + nearestColIndex * gridStepX;
        const minSnapX = colOffset;
        const maxSnapX = containerWidth - gridGap.value - item.width;
        snapX = Math.max(minSnapX, Math.min(snapX, maxSnapX));

        // --- Y 轴吸附 (新增) ---
        const gridStepY = Math.round(gridCellHeight.value) + gridGap.value;
        const nearestRowIndex = Math.round((item.y - colOffset) / gridStepY);
        let snapY = colOffset + nearestRowIndex * gridStepY;
        const minSnapY = colOffset;
        const maxSnapY = containerHeight - gridGap.value - item.height; // 新增
        snapY = Math.max(minSnapY, Math.min(snapY, maxSnapY)); // 新增

        // --- 更新吸附线 (修改) ---
        snapGuide.value.x = { show: Math.abs(item.x - snapX) < 10, pos: snapX };
        snapGuide.value.y = { show: Math.abs(item.y - snapY) < 10, pos: snapY }; // 修改
    };

    const onDragEnd = (index) => {
        const item = components.value[index];
        const swapped = handleSwapCollision(item);

        if (!swapped) {
            const container = gridContainer.value;
            if (!container) return;

            const { clientWidth: containerWidth, clientHeight: containerHeight } = container; // 新增 containerHeight
            const colOffset = gridGap.value;

            // --- X 轴对齐 (不变) ---
            const gridStepX = Math.round(gridCellWidth.value) + gridGap.value;
            const nearestColIndex = Math.round((item.x - colOffset) / gridStepX);
            let targetX = colOffset + nearestColIndex * gridStepX;
            const minX = colOffset;
            const maxX = containerWidth - item.width + gridGap.value * 3;
            item.x = Math.max(minX, Math.min(targetX, maxX));

            // --- Y 轴对齐 (新增) ---
            const gridStepY = Math.round(gridCellHeight.value) + gridGap.value; // 新增
            const nearestRowIndex = Math.round((item.y - colOffset) / gridStepY); // 新增
            let targetY = colOffset + nearestRowIndex * gridStepY; // 新增
            const minY = colOffset; // 新增
            const maxY = containerHeight - item.height + gridGap.value * 3; // 新增
            item.y = Math.max(minY, Math.min(targetY, maxY)); // 新增
        }

        snapGuide.value.x.show = false;
        snapGuide.value.y.show = false; // 新增
        delete item.startX;
        delete item.startY;
    };

    const onResizeStart = (id) => {
        selectedId.value = id;
    };

    const onResizing = (index, rect) => {
        // 在 onResizeEnd 中统一处理，此函数可留空或添加实时约束
    };

    const onResizeEnd = (index, rect) => {
        const item = components.value[index];
        const container = gridContainer.value;
        if (!container) return;

        const gridStepX = Math.round(gridCellWidth.value) + gridGap.value;
        const gridStepY = Math.round(gridCellHeight.value) + gridGap.value;
        const colOffset = gridGap.value;

        const startColIndex = Math.round((item.x - colOffset) / gridStepX);
        const startRowIndex = Math.round((item.y - colOffset) / gridStepY);

        const endColIndex = Math.round((rect.x + rect.w - colOffset) / gridStepX);
        const endRowIndex = Math.round((rect.y + rect.h - colOffset) / gridStepY);

        const nearestColSpan = Math.max(1, endColIndex - startColIndex);
        const nearestRowSpan = Math.max(1, endRowIndex - startRowIndex);

        item.width = gridCellWidth.value * nearestColSpan + gridGap.value * (nearestColSpan - 1);
        item.height = gridCellHeight.value * nearestRowSpan + gridGap.value * (nearestRowSpan - 1);
        item.x = rect.x;
        item.y = rect.y;

        item.xEnd = item.x + item.width;
        item.yEnd = item.y + item.height;

        resolveResizeCollisions();
    };


    // --- 碰撞解决逻辑 ---

    const handleSwapCollision = (draggedItem) => {
        let bestMatch = null;
        let maxOverlap = 0;

        for (const otherItem of components.value) {
            if (draggedItem.id === otherItem.id) continue;
            if (checkCollision(draggedItem, otherItem)) {
                const overlapX = Math.min(draggedItem.x + draggedItem.width, otherItem.x + otherItem.width) - Math.max(draggedItem.x, otherItem.x);
                const overlapY = Math.min(draggedItem.y + draggedItem.height, otherItem.y + otherItem.height) - Math.max(draggedItem.y, otherItem.y);
                const overlapArea = overlapX * overlapY;
                if (overlapArea > maxOverlap) {
                    maxOverlap = overlapArea;
                    bestMatch = otherItem;
                }
            }
        }

        if (bestMatch) {
            const { x: targetX, y: targetY } = bestMatch;
            bestMatch.x = draggedItem.startX;
            bestMatch.y = draggedItem.startY;
            draggedItem.x = targetX;
            draggedItem.y = targetY;
            // 触发视图更新
            bestMatch.version = (bestMatch.version || 0) + 1;
            draggedItem.version = (draggedItem.version || 0) + 1;
            return true;
        }
        return false;
    };

    const resolveResizeCollisions = () => {
        let hasCollision = true;
        let iterations = 0;
        const maxIterations = components.value.length ** 2;

        while (hasCollision && iterations < maxIterations) {
            hasCollision = false;
            iterations++;

            const sorted = [...components.value].sort((a, b) => a.y - b.y || a.x - b.x);
            const containerWidth = gridContainer.value.clientWidth;

            for (let i = 0; i < sorted.length; i++) {
                for (let j = i + 1; j < sorted.length; j++) {
                    const itemA = sorted[i];
                    const itemB = sorted[j];

                    if (checkCollision(itemA, itemB)) {
                        hasCollision = true;
                        const newX = itemA.x + itemA.width + gridGap.value;
                        if (newX + itemB.width > containerWidth - gridGap.value) {
                            const maxBottom = Math.max(...components.value.map(c => c.y + c.height));
                            itemB.y = maxBottom + gridGap.value;
                            itemB.x = gridGap.value;
                        } else {
                            itemB.x = newX;
                        }
                        itemB.version = (itemB.version || 0) + 1;
                        break;
                    }
                }
                if (hasCollision) break;
            }
        }

        components.value.forEach(item => {
            item.xEnd = item.x + item.width;
            item.yEnd = item.y + item.height;
        });

        if (iterations >= maxIterations) {
            console.warn("布局调整：超过最大迭代次数。");
        }
    };

    // --- 返回暴露给组件的接口 ---
    return {
        selectedId,
        snapGuide,
        selectComponent,
        onDragStart,
        onDraging,
        onDragEnd,
        onResizeStart,
        onResizing,
        onResizeEnd
    };
}
